package com.zb.excel;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.Serializable;
import java.util.List;

/**
 * @Author WEN
 * @Date 2024/2/7 0007
 **/
public class ExcelFillCellMergeStrategy implements CellWriteHandler {

    /**
     * 合并字段的下标，如第一列到第五列：new int[]{0,1,2,3,4}
     */
    private int[] mergeColumnIndex;

    /**
     * 从第几行开始合并，如果表头占两行，这个数字就来2
     */
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategy(int[] mergeColumnIndex, int mergeRowIndex) {
        this.mergeColumnIndex = mergeColumnIndex;
        this.mergeRowIndex = mergeRowIndex;
    }

    @Override
    public void beforeCellCreate(CellWriteHandlerContext context) {
        CellWriteHandler.super.beforeCellCreate(context);
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
        CellWriteHandler.super.beforeCellCreate(writeSheetHolder, writeTableHolder, row, head, columnIndex, relativeRowIndex, isHead);
    }

    @Override
    public void afterCellCreate(CellWriteHandlerContext context) {
        CellWriteHandler.super.afterCellCreate(context);
    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        CellWriteHandler.super.afterCellCreate(writeSheetHolder, writeTableHolder, cell, head, relativeRowIndex, isHead);
    }

    @Override
    public void afterCellDataConverted(CellWriteHandlerContext context) {
        CellWriteHandler.super.afterCellDataConverted(context);
    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        CellWriteHandler.super.afterCellDataConverted(writeSheetHolder, writeTableHolder, cellData, cell, head, relativeRowIndex, isHead);
    }

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        CellWriteHandler.super.afterCellDispose(context);
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList,
                                 Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 当前行
        int curRowIndex = cell.getRowIndex();
        // 当前列
        int curColIndex = cell.getColumnIndex();
        if (curRowIndex > mergeRowIndex) {
            for (int col : mergeColumnIndex) {
                if (curColIndex == col) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        // 获取当前行的当前列的数据和上一行的当前列的列数据，通过上一行的数据是否相同进行合并
        // 当前列数据
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Row preRow = cell.getSheet().getRow(curRowIndex - 1);
        if (null ==  preRow) {
            // 当获取不到上一行数据时，使用缓存sheet中的数据
            preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex -1);
        }
        Cell preCell = preRow.getCell(curColIndex);
        // 上一列数据
        Object preData = preCell.getCellTypeEnum() == CellType.STRING? preCell.getStringCellValue() : preCell.getNumericCellValue();
        // 比较当前行的第一列的单元格与上一行是否相同，相同合并当前单元格与上一行
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
            boolean isMerged = true;
            CellRangeAddress cellAddresses = null;
            for (int i = 0; i < mergedRegions.size(); i++) {
                if (isMerged) {
                    cellAddresses = mergedRegions.get(i);
                    if (cellAddresses.isInRange(curRowIndex - 1, curColIndex)) {
                        sheet.removeMergedRegion(i);
                        cellAddresses.setLastRow(curRowIndex);
                        sheet.addMergedRegion(cellAddresses);
                        isMerged = false;
                    }
                }
            }
            // 若上一个单元格未被合并，则新增合并单元
            if (isMerged) {
                sheet.addMergedRegion(new CellRangeAddress(curRowIndex -1, curRowIndex, curColIndex, curColIndex));
            }

        }
    }
}
